﻿using System.ComponentModel;
using System.Windows.Controls.Primitives;
using System.Windows.Automation;

// Author: Miroslav Matula m.matula@alutam.cz 
// Date : 31/8/2010

namespace System.Windows.Controls
{
  [TemplatePart(Name = wait_elementBuCancel, Type = typeof(ButtonBase))]
  public class WaitControl : Control
  {
    private const string wait_BuCancelTextBoxAutomationId = "Cancel";
    private const string wait_elementBuCancel = "ButtonCancel";    

    public WaitControl()
    {
      this.DefaultStyleKey = typeof(WaitControl);
      _bw = new BackgroundWorker();
      _bw.WorkerSupportsCancellation = true;
      _bw.DoWork += new DoWorkEventHandler(bw_DoWork);
      if(System.ComponentModel.DesignerProperties.IsInDesignTool) {
        Height = 2;
        Width = 2;
      }
      Loaded += (s,a) => {
        //OnApplyTemplate();
      };
    }
    public ButtonBase ButtonCancel { get; protected set; }

    private BackgroundWorker _bw;
    private bool _isComplete;
    private bool _contentIsLoaded=false;


    public bool IsBusy
    {
      get { return (bool)GetValue(IsBusyProperty); }
      set { SetValue(IsBusyProperty, value); }
    }
    public static readonly DependencyProperty IsBusyProperty =
        DependencyProperty.Register("IsBusy", typeof(bool), typeof(WaitControl), new PropertyMetadata(false, new PropertyChangedCallback(OnIsBusyChanged)));//
		private static void OnIsBusyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
      if(System.ComponentModel.DesignerProperties.IsInDesignTool) return;
      if((bool)e.NewValue) {
        ((WaitControl)d).BeginWaitMode();
      } else {
        ((WaitControl)d).EndWaitMode();
      }
		}

    public event RoutedEventHandler Cancel;
    

    public override void OnApplyTemplate()
    {
      base.OnApplyTemplate();
      //-- Cancel --------------------------
      if(ButtonCancel != null) ButtonCancel.Click -= new RoutedEventHandler(ButtonCancel_Click);  
      ButtonCancel = GetTemplateChild(wait_elementBuCancel) as ButtonBase;
      if(ButtonCancel != null) {
        ButtonCancel.Click += new RoutedEventHandler(ButtonCancel_Click);
        AutomationProperties.SetAutomationId(this.ButtonCancel, wait_BuCancelTextBoxAutomationId);
      }
      _contentIsLoaded = true;
      if(IsBusy) BeginWaitMode();
    }

    private void BeginWaitMode()
    {
      Dispatcher.BeginInvoke(() => {
        Opacity = 1D;
        Visibility = Visibility.Visible;
      });

      if(!_contentIsLoaded) return;
      //-- BackgroundWorker
      _isComplete = false;
      _bw.RunWorkerAsync(this);
    }
    private void EndWaitMode()
    {
      Dispatcher.BeginInvoke(() => {
        Visibility = Visibility.Collapsed;
        if(_bw.IsBusy) _bw.CancelAsync();
        _isComplete = true;
      });
    }

    //----------
    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
      Dispatcher.BeginInvoke(() => {
        ButtonCancel.Visibility = Visibility.Collapsed;
        var ii = ActualWidth;
      });
      int cnt = 0;
      do {
          if(cnt == 7) {
            Dispatcher.BeginInvoke(() => Opacity = 1); 
          }
          if(cnt == 15) {
            Dispatcher.BeginInvoke(() => {
              ButtonCancel.IsEnabled = true;
              ButtonCancel.Visibility = Visibility.Visible;
            });
          }

        if(_isComplete) {
          e.Result = e.Argument;
          break;
        }
        System.Threading.Thread.Sleep(50);
        cnt++;
      } while(true);
    }


    void ButtonCancel_Click(object sender, RoutedEventArgs e)
    {
      _isComplete = true;
      ButtonCancel.IsEnabled = false;
      if(_bw.IsBusy) _bw.CancelAsync();
      if(Cancel != null) {
        Cancel(this, new  RoutedEventArgs());
      }
    }
  }
}
